#include "structdef.h"
#include "lex.yy.c"
#include "povparser.h"

POVObject * readPOVFile(char * filename)
{
    FILE * f = fopen(filename,"r");
    if(f==NULL)
        return NULL;
    yyrestart(f);
    POVObject * o = new POVObject();

    POVMesh * m;
    std::string lastName;
    struct Token t;
    do{
        t = readNextToken();
        switch(t.token)
        {
            case TOKEN_DECLARATION_NAME:
                {
   //                 printf("Declaration:%s\n",t.text);
                    lastName = std::string(t.text);
                }
                break;
            case TOKEN_MESH_START:
                {
                    m=readMesh();
                    m->setName(lastName);
                    o->addMesh(m);
                }
                break;
        }

        t.clean();
    }
    while(t.token!=TOKEN_FIN);

    return o;
}


POVMesh * readMesh()
{
    struct Token t;
    POVTriangle tri;
    POVMesh * m = new POVMesh();

    do{
        t=readNextToken();
        switch(t.token)
        {
            case TOKEN_TRIANGLE_START:
                {
                    tri = readTriangle();
                    m->addTriangle(tri);
                }
                break;

            case TOKEN_ROTATE_X:
                {
                   float rotx = readRotation();
                   m->setRotX(rotx);
                   printf("Rotation X:%f\n",rotx);
                }
                break;
        
            case TOKEN_ROTATE_Y:
                {
                   float roty = readRotation();
                   m->setRotY(roty);
                   printf("Rotation Y:%f\n",roty);
                }
                break;
        
            case TOKEN_ROTATE_Z:
                {
                   float rotz = readRotation();
                   m->setRotZ(rotz);
                   printf("Rotation Z:%f\n",rotz);
                }
                break;
            // TODO añadir el TOKEN de textura, para crear las texturas del arbol 

            default:
                {
             /*       if(t.mustFree)
                        printf("read token: %s\n",t.text);
                    else
                        printf("read token: %i\n",t.token);
                */
                }
        }
                t.clean();

    }while(t.token!=TOKEN_MESH_END && t.token!=TOKEN_FIN);
    printf("triangles:%i\n",m->getNumberOfTris());
    return m;
}

POVTriangle readTriangle()
{
    struct Token t;
    POVTriangle tri;
    POVPoint po;
    po.x = 0.0; po.y = 0.0; po.z = 0.0;
    tri.pv[0]=po; tri.pv[1]=po;tri.pv[2]=po;

    int readPoints = 0;
   
    do{
        t=readNextToken();
        if(t.token == TOKEN_BEGIN_POINT)
        {
            if(readPoints>3)
            {
                //TODO lanzar una excepcion
            }

            po = readPoint();

            tri.pv[readPoints]=po;
            readPoints++;
        }

        t.clean();
    }
    while(t.token!=TOKEN_TRIANGLE_END);
    
    return tri;
}

POVPoint readPoint()
{
    int floatsRead=0;
    POVPoint p;
    p.x=0;
    p.y=0;
    p.z=0;
    struct Token t;
   
    do{
        t=readNextToken();
        if(t.token != TOKEN_NUMBER && t.token != TOKEN_IRRELEVANT || floatsRead>3 )
        {
            //TODO añadir aqui una excepcion
        }
        else
        {
            p.v[floatsRead] = t.f;
         
            floatsRead++;
        }
    }
    while(t.token != TOKEN_END_POINT);
    return p;
}

float readRotation()
{
    struct Token t;
    t=readNextToken();
    t.clean();
    return t.f;
}


